<!DOCTYPE html>
<html>

<head>
  <title>cannon.js - splitsolver demo</title>
  <meta charset="utf-8">
  <link rel="stylesheet" href="css/style.css" type="text/css" />
  <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
</head>

<body>
  <script src="../../feng3d/out/feng3d.js"></script>
  <script src="../out/cannon.js"></script>
  <script src="../build/cannon.demo.js"></script>
  <script src="../libs/dat.gui.js"></script>
  <script src="../libs/Three.js"></script>
  <script src="../libs/TrackballControls.js"></script>
  <script src="../libs/Detector.js"></script>
  <script src="../libs/Stats.js"></script>
  <script src="../libs/smoothie.js"></script>
  <script>

    /**
     * This demonstrates why it can be good to use the SplitSolver.
     * If you have put a nonzero tolerance on a solver, it will in stop iterating when
     * the total error is small, in other words: when the system is solved "good enough".
     * When simulating larger systems with more equations, the error will add up,
     * and the solver will need more iterations/work to reach the "good enough" level.
     *
     * The SplitSolver splits the system into independent parts, and runs a subsolver
     * on each part. The total error in a subsystem will many times be smaller than in
     * the large system, so we can many times cut down on the total number of iterations we do.
     *
     * Another interesting fact is that we *could* run the subsystems in separate threads and
     * speed up the computing even more. However, CANNON runs in one thread for now.
     *
     * The first scene uses the split solver and the second one does not. Turn on the
     * profiling plot and enjoy!
     */

    var demo = new CANNON.Demo();
    var size = 0.5;

    var shape = new CANNON.Sphere(size);
    var shape = new CANNON.Box(new CANNON.Vector3(size * 0.5, size * 0.5, size * 0.5));
    demo.addScene("with split", function ()
    {
      createScene(demo, shape, true);
    });
    demo.addScene("without split", function ()
    {
      createScene(demo, shape, false);
    });

    demo.start();

    function createScene(demo, shape, split)
    {

      // Create world
      var world = demo.getWorld();
      world.gravity.set(0, 0, -10);
      world.broadphase = new CANNON.NaiveBroadphase();

      var solver = new CANNON.GSSolver();
      solver.iterations = 50;
      world.defaultContactMaterial.contactEquationStiffness = 1e7;
      world.defaultContactMaterial.contactEquationRelaxation = 5;
      solver.tolerance = 0.0001;
      if (split)
        world.solver = new CANNON.SplitSolver(solver);
      else
        world.solver = solver;

      // ground plane
      var groundShape = new CANNON.Plane();
      var groundBody = new CANNON.Body({ mass: 0 });
      groundBody.addShape(groundShape);
      world.addBody(groundBody);
      demo.addVisual(groundBody);

      // Shape on plane
      var N = 5;
      for (var i = 0; i < N; i++)
      {
        for (var j = 0; j < N; j++)
        {
          var shapeBody = new CANNON.Body({ mass: 1 });
          shapeBody.addShape(shape);
          shapeBody.position.set((i - N * 0.5) * size * 2 * 1.1,
            (j - N * 0.5) * size * 2 * 1.1,
            size * 1.05);
          world.addBody(shapeBody);
          demo.addVisual(shapeBody);
        }
      }


      var shapeBody = new CANNON.Body({ mass: 1 });
      shapeBody.addShape(shape);
      shapeBody.position.set(size, size,
        size * 5);
      world.addBody(shapeBody);
      demo.addVisual(shapeBody);
    }

  </script>
</body>

</html>